package com.yugao.fintech.antelope.mps.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yugao.fintech.antelope.infra.InfraApi;
import com.yugao.fintech.antelope.infra.module.group.model.rqrs.DataGroupBase;
import com.yugao.fintech.antelope.infra.module.group.model.rqrs.DataGroupListReq;
import com.yugao.fintech.antelope.infra.module.group.model.rqrs.DataGroupResp;
import com.yugao.fintech.antelope.base.model.enums.DataGroupBizTypeEnum;
import com.yugao.fintech.antelope.mps.api.constatnts.ChannelCodeEnum;
import com.yugao.fintech.antelope.mps.assembly.MsgPushTaskAssembly;
import com.yugao.fintech.antelope.mps.manager.MsgHistoryManager;
import com.yugao.fintech.antelope.mps.manager.MsgPushTaskManager;
import com.yugao.fintech.antelope.mps.manager.MsgTemplateManager;
import com.yugao.fintech.antelope.mps.mapper.MsgPushTaskMapper;
import com.yugao.fintech.antelope.mps.model.entity.MsgPushTask;
import com.yugao.fintech.antelope.mps.model.rqrs.channel.ChannelResp;
import com.yugao.fintech.antelope.mps.model.rqrs.task.PushTaskListReq;
import com.yugao.fintech.antelope.mps.model.rqrs.task.PushTaskResp;
import com.yugao.fintech.antelope.mps.model.rqrs.task.PushTaskSaveReq;
import com.yugao.fintech.antelope.mps.model.rqrs.task.PushTaskUpdateReq;
import com.yugao.fintech.antelope.mps.service.MsgPushTaskService;
import com.yugao.fintech.framework.assistant.utils.CollectionUtils;
import com.yugao.fintech.framework.assistant.utils.exception.BizException;
import com.yugao.fintech.framework.desensitization.annotations.FieldBindHandle;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 消息推送任务
 */
@Slf4j
@Service
public class MsgPushTaskServiceImpl extends ServiceImpl<MsgPushTaskMapper, MsgPushTask> implements IService<MsgPushTask>, MsgPushTaskService {
    @Autowired
    private MsgPushTaskManager pushTaskManager;
    @Autowired
    private MsgTemplateManager templateManager;
    @Autowired
    private MsgHistoryManager historyManager;
    @Autowired
    private MsgPushTaskAssembly pushTaskAssembly;
    @Autowired
    private InfraApi infraApi;

    /**
     * 分页查询 消息推送任务
     *
     * @return 返回分页数据
     */
    @Override
    @FieldBindHandle
    public List<PushTaskResp> listPushTask(PushTaskListReq req) {
        LambdaQueryWrapper<MsgPushTask> queryWrapper = MsgPushTask.lqw()
            .eq(Objects.nonNull(req.getGroupId()), MsgPushTask::getGroupId, req.getGroupId())
            .eq(StringUtils.isNotEmpty(req.getReceiverType()), MsgPushTask::getReceiverType, req.getReceiverType())
            .like(StringUtils.isNotEmpty(req.getKeyword()), MsgPushTask::getTaskCode, req.getKeyword())
            .like(StringUtils.isNotEmpty(req.getKeyword()), MsgPushTask::getName, req.getKeyword())
            .orderByDesc(MsgPushTask::getCreatedAt).orderByDesc(MsgPushTask::getGroupId);
        List<MsgPushTask> taskList = this.list(queryWrapper);

        List<Long> groupIds = taskList.stream().map(MsgPushTask::getGroupId).distinct()
                .collect(Collectors.toList());
        Map<Long, String> groupNameMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(groupIds)) {
            DataGroupListReq groupReq = new DataGroupListReq().setBizType(DataGroupBizTypeEnum.MSG_PUSH_TASK.getType())
                    .setIds(groupIds);
            Map<Long, String> dbGroupNameMap = infraApi.listDataGroup(groupReq).stream()
                    .collect(Collectors.toMap(DataGroupResp::getId, DataGroupResp::getName));
            groupNameMap.putAll(dbGroupNameMap);
        }

        return taskList.stream().map(e -> {
            PushTaskResp resp = pushTaskAssembly.toPushTaskResp(e);
            resp.setGroupName(groupNameMap.get(e.getGroupId()));
            return resp;
        }).collect(Collectors.toList());
    }

    /**
     * 根据主键查询 消息推送任务
     *
     * @param id 主键
     * @return 返回记录，没有返回null
     */
    @Override
    @FieldBindHandle
    public PushTaskResp getPushTaskById(Long id) {
        MsgPushTask entity = this.getById(id);
        if (Objects.isNull(entity)) {
            return null;
        }

        String groupName = "";
        if (Objects.nonNull(entity.getGroupId())) {
            groupName = Optional.ofNullable(infraApi.getDataGroup(entity.getGroupId())).map(DataGroupBase::getName).orElse("");
        }
        PushTaskResp resp = pushTaskAssembly.toPushTaskResp(entity);
        resp.setGroupName(groupName);
        return resp;
    }

    /**
     * 保存 消息推送任务
     *
     * @param req 新增的记录
     * @return 返回影响行数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveMsgPushTask(PushTaskSaveReq req) {
        // 保存推送任务
        MsgPushTask entity = pushTaskAssembly.toPushTask(req);
    	return pushTaskManager.savePushTask(entity);
    }

    /**
     * 更新 消息推送任务
     *
     * @param req 修改的记录
     * @return 返回影响行数
     */
    @Override
    @FieldBindHandle
    @Transactional(rollbackFor = Exception.class)
    public boolean updateMsgPushTaskById(PushTaskUpdateReq req) {
        MsgPushTask entity = pushTaskAssembly.toPushTask(req);
        return pushTaskManager.updatePushTask(entity);
    }

    /**
     * 通过id删除 消息推送任务
     *
     * @param id 删除的主键
     * @return 返回影响行数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deletePushTaskById(Long id) {
        // 删除消息推送历史
        templateManager.deleteTemplateByTaskIds(Collections.singletonList(id));
        // 删除消息推送模板
        historyManager.deleteHistoryByTaskIds(Collections.singletonList(id));
    	return this.removeById(id);
    }
    
    /**
     * 通过ids删除 消息推送任务
     *
     * @param ids 删除的主键
     * @return 返回影响行数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deletePushTaskByIds(List<Long> ids) {
        // 删除消息推送历史
        templateManager.deleteTemplateByTaskIds(ids);
        // 删除消息推送模板
        historyManager.deleteHistoryByTaskIds(ids);
    	return this.removeByIds(ids);
    }

    @Override
    public MsgPushTask getPushTaskByCode(String taskCode) {
        MsgPushTask task = this.getOne(MsgPushTask.lqw().eq(MsgPushTask::getTaskCode, taskCode));
        if (Objects.isNull(task)) {
            throw new BizException("未知消息推送任务编码 taskCode: {}", taskCode);
        }
        return task;
    }

    @Override
    public List<ChannelResp> listChannel() {
        return Arrays.stream(ChannelCodeEnum.values()).map(e -> {
            ChannelResp resp = new ChannelResp();
            resp.setChannelCode(e.getCode());
            resp.setName(e.getName());
            return resp;
        }).collect(Collectors.toList());
    }

    @Override
    public boolean batchDeleteGroup(List<Long> ids) {
        DataGroupListReq groupReq = new DataGroupListReq();
        groupReq.setBizType(DataGroupBizTypeEnum.MSG_PUSH_TASK.getType()).setIds(ids);
        List<DataGroupResp> groupList = infraApi.listDataGroup(groupReq);
        List<Long> groupIds = groupList.stream().map(DataGroupResp::getId).distinct().collect(Collectors.toList());
        if (this.count(MsgPushTask.lqw().in(MsgPushTask::getGroupId, groupIds)) > 0) {
            throw new BizException("所删除的功能组下有未删除的任务, 请全部删除后再删除组");
        }
        infraApi.batchDeleteDataGroup(DataGroupBizTypeEnum.MSG_PUSH_TASK, ids);
        return true;
    }
}
